package models.security;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import framework.base.BaseModel;
import framework.utils.ArrayUtil;
import framework.utils.StringUtil;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import play.data.validation.Check;
import play.data.validation.CheckWith;
import play.data.validation.MaxSize;
import play.data.validation.Required;

@Entity
@Table(name="T_ROLE")
public class Role extends BaseModel {
    @Required(message="角色名不能为空")
    @CheckWith(value=RoleNameUniqueCheck.class,message="角色名已存在")
    @MaxSize(value=16,message="名称不能超过16个字符")
    public String name;
    
    public int ifSystem;
    
    @ManyToMany(cascade=CascadeType.REFRESH,fetch=FetchType.LAZY)
    @JoinTable(name="T_ROLE_PERMISSION")
    public List<Permission> permissions = new ArrayList<Permission>();
    //角色
    @ManyToMany(mappedBy="roles")
    public List<User> users = new ArrayList<User>();
    
    
    public Role(){
        super();
        this.ifSystem = 0;
        this.status=USE_STATUS;
        this.createdAt = new Date();
        this.updatedAt = new Date();
    }
    
    public Role(String name){
        super();
        this.ifSystem = 0;
        this.status = USE_STATUS;
        this.name = name;
        this.createdAt = new Date();
        this.updatedAt = new Date();
    }
    
    /**
     * 根据名字查找角色信息
     * @return
     */
    public static Role findByName(String name){
        String sql="from Role a where a.name=? and a.status=?";
        return Role.find(sql,name,USE_STATUS).first();
    }
    
    static class RoleNameUniqueCheck extends Check{
        @Override
        public boolean isSatisfied(Object role, Object value) {
            boolean rcode = false;
            Role  r = null;
            if(role instanceof Role){
                 r = (Role) role;
            }
            if(null!=r){
                Role obj = Role.findByName(value.toString());
                if(null==obj || obj.id.equals(r.id)){
                    rcode = true;
                }
            }
            return rcode;
        }
    }
    
    
    /**
     * 构造权限树
     */
    public  JSONArray toMenuJson(){
        List<Permission> roots = Permission.rootPermissions();
        Map<String,String> dics = Resource.resourcesDic();
        Set<String> codes = this.allResourceCodes();
        List<Permission> nodes = null;
        List<Permission> actions = null;
        JSONArray array = new JSONArray();
        JSONObject obj = new JSONObject();
        obj.put("id",0);
        obj.put("pId", -1);
        obj.put("name", "系统资源");
        obj.put("ptype", "rootPoint");
        obj.put("open", true);
        array.add(obj);
        for(Permission p : roots){
            obj = new JSONObject();
            obj.put("id",p.id);
            obj.put("pId", 0);
            obj.put("name", StringUtil.trim(dics.get(p.code)));
            obj.put("ptype", "root");
            obj.put("open", true);
            if(codes.contains(p.code)){
                array.add(obj);
            }
            nodes = p.queryNodes();
            for(Permission node : nodes){
                obj = new JSONObject();
                obj.put("id",node.id);
                obj.put("pId", p.id);
                obj.put("name", StringUtil.trim(dics.get(node.code)));
                obj.put("ptype", "node");
                obj.put("open", true);
                if(codes.contains(node.code)){
                    array.add(obj);
                }
                actions = node.queryActions();
                for(Permission action : actions){
                    obj = new JSONObject();
                    obj.put("id",action.id);
                    obj.put("pId", node.id);
                    obj.put("name", StringUtil.trim(dics.get(action.code)));
                    obj.put("ptype", "action");
                    if(codes.contains(action.code)){
                        array.add(obj);
                    }
                }
            }
        }
        return array;
    }
    
    public void grant(String[] pids){
        if(!ArrayUtil.isEmpty(pids)){
           Permission permission = null;
           for(String id : pids){
             permission = Permission.findById(id);
             this.permissions.add(permission);
           }
        }
    }
    
    
    public Set<String> allResourceCodes(){
        List<Permission> permissions = this.permissions;
        Set<String> codes = new HashSet<String>();
        for(Permission p : permissions){
            codes.add(p.code);
            codes.add(p.rootCode());
        }
        return codes;
    }
    
    /**
     * 是否可用
     * @return
     */
    public boolean isActive(){
      return this.status == USE_STATUS;  
    }
    
}
